<template> 
    <div v-if="visible" class="dialog-overlay">
  <div  class="container" :class="{ 'maximized': isMaximized }">
    <div class="window-controls">
      <button class="window-control" @click="toggleMaximize" title="全屏/还原">
        <svg v-if="isMaximized" width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
          <path d="M8 3V5H5V8H3V3H8Z" fill="currentColor"/>
          <path d="M21 8V3H16V5H19V8H21Z" fill="currentColor"/>
          <path d="M3 16V21H8V19H5V16H3Z" fill="currentColor"/>
          <path d="M19 16V19H16V21H21V16H19Z" fill="currentColor"/>
        </svg>
        <svg v-else width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
          <path d="M3 8V3H8V5H5V8H3Z" fill="currentColor"/>
          <path d="M21 3H16V5H19V8H21V3Z" fill="currentColor"/>
          <path d="M8 21H3V16H5V19H8V21Z" fill="currentColor"/>
          <path d="M19 19V16H21V21H16V19H19Z" fill="currentColor"/>
        </svg>
      </button>
      <button class="window-control close-btn" @click="closeDialog" title="关闭">
        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
          <path d="M18 6L6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
          <path d="M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
        </svg>
      </button>
    </div>
    <h1 class="title">{{route.meta.title || '系统'}} 智能对话</h1>
 
    <!-- 对话历史 -->
    <div class="chat-history">
      <div v-for="(message, index) in messages" :key="index" class="message-item">
        <div class="message-content" :class="[message.role, { 'is-streaming':isStreaming }]">
          <div v-if="message.role === 'user'" class="user-avatar">用户</div>
          <div v-else class="bot-avatar">AI</div>
          <div v-html="renderMarkdown(message.content)" class="markdown-content"></div>
        </div>
      </div>
    </div>

    <!-- 输入区域 -->
    <div class="input-area">
      <textarea
        v-model="currentInput"
        placeholder="输入你的问题..."
        class="textarea"
        @keyup.enter.prevent="sendMessage"
      ></textarea>
     <button 
      @click="handleActionButtonClick"
      class="action-btn"
      :class="{ 'streaming': isStreaming }"
      :disabled="!currentInput.trim() && !isStreaming"
    >
      <span v-if="isStreaming">
        <div class="streaming-dots">
          <span class="dot"></span>
          <span class="dot"></span>
          <span class="dot"></span>
        </div>
        停止生成
      </span>
      <span v-else>
        {{ isStreaming ? '停止生成' : '发送' }}
      </span>
    </button>
        </div>
  </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
import { marked } from 'marked'
import hljs from 'highlight.js'
import { useRoute } from 'vue-router'
import { addGbAiAskResp } from '@/api/buss/gbaiaskresp.js'
 
// 需要安装marked库来解析Markdown
 // 初始化marked配置
marked.setOptions({
  breaks: true,
  gfm: true,
  highlight: (code) => hljs.highlightAuto(code).value
})
const messages = ref([])
const currentInput = ref('')
const isStreaming = ref(false)
const controller = new AbortController()
const abortController = ref(new AbortController()) 
const visible = ref(false);
const isMaximized = ref(false);

// 处理动作按钮点击
const handleActionButtonClick = () => {
  if (isStreaming.value) {
    stopGeneration()
  } else {
    sendMessage()
  }
}
// 停止生成
const stopGeneration = () => {
  try {
    if (abortController.value && !abortController.value.signal.aborted) {
      abortController.value.abort()
      console.log('已中止当前生成请求')
    }
    abortController.value = new AbortController()
    isStreaming.value = false
    
    // 确保移除所有流式传输中的消息
    messages.value = messages.value.map(msg => {
      if (msg.isStreaming) {
        return {...msg, isStreaming: false}
      }
      return msg
    }).filter(msg => msg.content.trim().length > 0)
    
    console.log('停止生成完成，当前消息数:', messages.value.length)
  } catch (error) {
    console.error('停止生成时出错:', error)
  }
}
// 发送消息并处理流式响应
const sendMessage = async () => {
  if (!currentInput.value.trim()) return

  // 添加用户消息
  messages.value.push({
    role: 'user',
    content: currentInput.value
  })

  // 清空输入框
  const userInput = currentInput.value
  currentInput.value = ''

 
  // 创建新对话上下文
  const newMessages = [...messages.value]
 try {
    isStreaming.value = true
    const response = await fetch(import.meta.env.VITE_APP_DEEPSEEK_APIURL, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ' + import.meta.env.VITE_APP_DEEPSEEK_APIKEY // 替换为实际API Key
      },
      body: JSON.stringify({
        model: 'deepseek-chat',
        messages: newMessages,
        stream: true,
       temperature: 0.7,
        max_tokens: 512
      }),
      signal: controller.signal
    })

    if (!response.ok) throw new Error('API请求失败')

    const reader = response.body.getReader()
    const decoder = new TextDecoder()
    let partialResult = ''
    let isFirstChunk = true

    while (true) {
      const { done, value } = await reader.read()
      if (done) break

      // 处理流式数据块
      const chunks = decoder.decode(value).split('\n\n')
      for (const chunk of chunks) {
        if (chunk.startsWith('data: ')) {
          try {
            const data = JSON.parse(chunk.replace('data: ', ''))
              // 跳过心跳包
            if (data.event === 'heartbeat') continue
            if (data.choices?.[0]?.delta?.content) {
              partialResult += data.choices[0].delta.content
                 // 仅在接收到第一个分片时创建新消息
              if (isFirstChunk) {
                messages.value.push({
                  role: 'assistant',
                  content: '',
                  isStreaming: true
                })
                isFirstChunk = false
              }
               // 更新最新消息的内容
              const lastMessage = messages.value[messages.value.length - 1]
              lastMessage.content = partialResult
            }
                // 处理结束标记
            if (data.event === 'end' || data.finish_reason) {
              console.log('收到流式传输结束标记')
              // 确保更新最后一条消息
              const lastIndex = messages.value.length - 1
              if (lastIndex >= 0) {
                // 创建新消息对象确保响应式更新
                const updatedMessage = {
                  ...messages.value[lastIndex],
                  isStreaming: false,
                  content: partialResult
                }
                // 强制重新渲染
                messages.value = []
                nextTick(() => {
                  messages.value = [...messages.value.slice(0, lastIndex), updatedMessage]
                  console.log('流式传输已正常结束，更新后的消息:', 
                    JSON.parse(JSON.stringify(updatedMessage)))
                })
              }
              isStreaming.value = false
              isFirstChunk = true
              partialResult = ''
              break
            }
            
          } catch (e) {
            // 忽略心跳包等非JSON内容
          }
        }
      }
    }
  } catch (error) {
    console.error('流式传输错误:', error)
    messages.value.push({
      role: 'assistant',
      content: '生成过程中发生错误，请重试'
    })
  } finally {
   isStreaming.value = false
     const lastMessage = messages.value[messages.value.length - 1]
                if (lastMessage?.role === 'assistant') {
                  console.log('准备记录日志:', {
                    ask: prompt,
                    response: lastMessage.content,
                    MenuName: 'deepseek-chat'
                  })
                  addGbAiAskResp({
                    ask: prompt,
                    response: lastMessage.content,
                    ChatModel: 'deepseek-chat',
                    createTime: new Date().toISOString()
                  })
                  .then(() => console.log('日志记录成功'))
                  .catch(e => {
                    console.error('日志记录失败:', e)
                    if (e.response) {
                      console.error('响应数据:', e.response.data)
                      console.error('状态码:', e.response.status)
                    }
                  })
                }
  }
}

// 渲染Markdown内容
const renderMarkdown = (text) => {
  return marked.parse(text || '')
}

// 组件卸载时取消请求
onBeforeUnmount(() => {
  controller.abort()
}) 
 
const route = useRoute()

function openDialog() {
  visible.value = true;
  console.log('当前路由信息:', {
    path: route.path,
    name: route.name,
    params: route.params,
    query: route.query,
    meta: route.meta
  })
}

function closeDialog() {
  visible.value = false;
  stopGeneration();
}

function toggleMaximize() {
  isMaximized.value = !isMaximized.value;
}

// 暴露打开对话框的方法给父组件
defineExpose({ openDialog });

</script>


<style scoped>
:root {
  --primary-color: #4361ee;
  --secondary-color: #3f37c9;
  --accent-color: #4895ef;
  --danger-color: #f72585;
  --success-color: #4cc9f0;
  --text-color: #2b2d42;
  --bg-color: #f8f9fa;
}

.dialog-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0,0,0,0.5);
  backdrop-filter: blur(5px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
  transition: all 0.3s ease;
}

.container {
  background: white;
  width: 90%;
  max-width: 800px;
  height: 90vh;
  border-radius: 16px;
  display: flex;
  flex-direction: column;
  box-shadow: 0 10px 25px rgba(0,0,0,0.2);
  overflow: hidden;
  transition: all 0.3s ease;
  position: relative;
}

.container.maximized {
  width: 100%;
  height: 100vh;
  max-width: none;
  border-radius: 0;
}

.window-controls {
  position: absolute;
  top: 0;
  right: 0;
  z-index: 10;
  display: flex;
  gap: 4px;
  padding: 8px;
}

.window-control {
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  background: none;
  border: none;
  border-radius: 4px;
  color: #666;
  transition: all 0.3s;
}

.window-control:hover {
  background: rgba(0,0,0,0.05);
  color: #333;
}

.window-control svg {
  transition: transform 0.2s;
}

.window-control:hover svg {
  transform: scale(1.1);
}

.close-btn:hover {
  background: rgba(244, 67, 54, 0.1);
  color: #f44336;
}

.title {
  text-align: center;
  color: var(--text-color);
  margin: 1.5rem 0;
  font-size: 1.8rem;
  position: relative;
  padding: 0 2rem;
  font-weight: 600;
}
.stop-btn {
  background: #e74c3c;
  color: white;
  padding: 0.5rem 1rem;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: opacity 0.3s;
}
 
.stop-btn:hover {
  opacity: 0.8;
}
.stop-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}.close-btn {
  background: none;
  border: none;
  font-size: 1.5rem;
  cursor: pointer;
  padding: 0 1rem;
  color: #666;
  transition: color 0.3s;
}
 
.close-btn:hover {
  color: #333;
}
 
.chat-history {
  flex: 1;
  overflow-y: auto;
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  padding: 1rem;
  background: #f8f9fa;
  margin: 1rem;
}

.message-item {
  margin-bottom: 1.5rem;
}

.message-content {
  display: flex;
  gap: 1rem;
  align-items: flex-start;
}

.user-avatar,
.bot-avatar {
  padding: 0.5rem 1rem;
  border-radius: 4px;
  min-width: 60px;
  text-align: center;
}

.user-avatar {
  background: #3498db;
  color: white;
}

.bot-avatar {
  background: #2ecc71;
  color: white;
}

.markdown-content {
  flex: 1;
  background: white;
  padding: 1rem;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  line-height: 1.6;
}

.markdown-content :deep(pre) {
  background: #2d2d2d;
  padding: 1rem;
  border-radius: 4px;
  overflow-x: auto;
}

.markdown-content :deep(code) {
  font-family: 'Fira Code', monospace;
  padding: 2px 4px;
  background: #f0f0f0;
  border-radius: 3px;
}

.input-area {
  display: flex;
  gap: 1rem;
  padding: 1rem;
  margin: 0 1rem 1rem;
  background: white;
  border-radius: 8px;
  box-shadow: 0 -2px 10px rgba(0,0,0,0.05);
}

@media (max-width: 600px) {
  .input-area {
    flex-direction: column;
    gap: 0.5rem;
  }
  
  .textarea {
    min-height: 80px;
  }
}

.textarea {
  flex: 1;
  min-height: 100px;
  max-height: 200px;
  padding: 1rem;
  font-size: 1rem;
  border: 2px solid #e0e0e0;
  border-radius: 8px;
  resize: vertical;
  transition: all 0.3s;
}

.textarea:focus {
  border-color: #3498db;
  outline: none;
  box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.2);
}

.textarea:focus {
  border-color: #3498db;
  outline: none;
}

.send-btn {
  background: #3498db;
  color: white;
  padding: 0 2rem;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  font-size: 1rem;
  transition: background 0.3s;
  white-space: nowrap;
}

.send-btn:hover:not(:disabled) {
  background: #2980b9;
}

.send-btn:disabled {
  background: #bdc3c7;
  cursor: not-allowed;
}

@media (max-width: 600px) {
  .input-area {
    flex-direction: column;
  }
  
  .send-btn {
    width: 100%;
  }
}
/* 添加流式传输动画 */
.message-content.assistant.is-streaming {
  position: relative;
  min-height: 40px;
  padding-right: 3rem;
}

.message-content.assistant.is-streaming::after {
  content: "•••";
  position: absolute;
  right: 1rem;
  bottom: 0.5rem;
  animation: blink 1s infinite;
}

/* 确保动画在非流式状态时完全移除 */
.message-content.assistant:not(.is-streaming)::after {
  content: none !important;
  display: none !important;
  visibility: hidden !important;
  height: 0 !important;
  width: 0 !important;
  overflow: hidden !important;
  position: absolute !important;
  right: -9999px !important;
  bottom: -9999px !important;
  animation: none !important;
  opacity: 0 !important;
}

@keyframes pulse {
  0% { opacity: 0.95; }
  50% { opacity: 1; }
  100% { opacity: 0.95; }
}
.action-btn {
  background: #3498db;
  color: white;
  border: none;
  padding: 0 1.5rem;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  white-space: nowrap;
}
 
.action-btn:hover:not(:disabled) {
  opacity: 0.9;
  transform: translateY(-1px);
}
 
.action-btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
 
.action-btn.streaming {
  background: #e74c3c;
}
 
.streaming-dots {
  display: flex;
  gap: 4px;
  animation: bounce 1.4s infinite;
}
 
.streaming-dots .dot {
  width: 6px;
  height: 6px;
  background: white;
  border-radius: 50%;
}
@keyframes blink {
  from { opacity: 0; }
  to { opacity: 1; }
}
</style>